<?php
/**
 * 文件目录处理
 *
 */
class File {
	private $_oFileInfo = null;
	private $_aInfo = array ();
	private $_aDefaultPort = array ('file' => null, 'http' => 80, 'ftp' => 21, 'sftp' => 22 );
	
	private function _parse($sUrl) {
		$aInfo = parse_url ( $sUrl );
		if (! $aInfo ['host'] && $aInfo ['scheme'] != 'file') {
			if (preg_match ( '/[a-z]/i', $aInfo ['scheme'] )) {
				$aInfo ['path'] = $aInfo ['scheme'] . ':' . $aInfo ['path'];
			}
			$aInfo ['scheme'] = 'file';
		}
		if (array_key_exists ( $aInfo ['scheme'], $this->_aDefaultPort )) {
			if ($aInfo ['scheme'] != 'file' && ! $aInfo ['port']) {
				$aInfo ['port'] = $this->_aDefaultPort [$aInfo ['scheme']];
			}
			$sId = self::_getId ( $aInfo );
			$this->_aInfo [$sId] = $aInfo;
			return $sId;
		} else {
			return false;
		}
	}
	
	private function _getId($aInfo) {
		unset ( $aInfo ['path'] );
		return md5 ( serialize ( $aInfo ) );
	}
	
	/**
	 * 列文件目录
	 * 
	 * @param $sPath 目录路径
	 * @param $sType 列出目录类型file只列文件 dir只列目录默认列出所有tree遍历目录同时$sMatch无效
	 * @param $sMatch 文件名通配符
	 * @return array
	 */
	public function ls($sPath, $sType = 'all', $sMatch = null) {
		if ($sType == null) {
			$sType = all;
		}
		$sId = self::_parse ( $sPath );
		$sType = strtolower ( $sType );
		if ($this->_aInfo [$sId] ['scheme'] == 'http') {
			return false;
		} elseif ($this->_aInfo [$sId] ['scheme'] == 'file') {
			return self::_ls ( $sPath, $sType, $sMatch );
		} else {
			$oObject = self::_getObject ( $sId );
			$oObject->connect ( $this->_aInfo [$sId] ['host'], $this->_aInfo [$sId] ['port'], $this->_aInfo [$sId] ['user'], $this->_aInfo [$sId] ['pass'] );
			return $oObject->ls ( $this->_aInfo [$sId] ['path'], $sType, $sMatch );
		}
	}
	
	private function _ls($sPath, $sType, $sMatch = null, $aResult = array()) {
		try {
			$aFiles = @scandir ( $sPath );
			if ($aFiles == false) {
				throw new ExceptionExt ( '目录' . $sPath . '不存在' );
			}
		} catch ( ExceptionExt $e ) {
			$e->showError ();
		}
		if ($sMatch != null && $sMatch != '*') {
			$sThisMatch = str_replace ( '.', '\.', $sMatch );
			$sThisMatch = str_replace ( '*', '.*', $sThisMatch );
			$sThisMatch = str_replace ( '?', '.?', $sThisMatch );
			$sThisMatch = '/^' . $sThisMatch . '$/';
		}
		foreach ( $aFiles as $sRow ) {
			if (! preg_match ( '/^[\.]+$/', $sRow )) {
				if ($sThisMatch != null && $sType != 'tree') {
					if (! preg_match ( $sThisMatch, $sRow )) {
						continue;
					}
				}
				$sFile = realpath ( $sPath . '/./' . $sRow );
				if ($sType == 'dir' && is_dir ( $sFile )) {
					$aResult [] = $sFile;
				} elseif ($sType == 'file' && ! is_dir ( $sFile )) {
					$aResult [] = $sFile;
				} elseif ($sType == 'all') {
					$aResult [] = $sFile;
				} elseif ($sType == 'tree') {
					if ($sThisMatch != null) {
						if (preg_match ( $sThisMatch, $sRow )) {
							$aResult [] = $sFile;
						}
					} else {
						$aResult [] = $sFile;
					}
					if (is_dir ( $sFile )) {
						$aResult = $this->_ls ( $sFile, 'tree', $sMatch, $aResult );
					}
				}
			}
		}
		return $aResult;
	}
	
	/**
	 * 创建目录
	 *
	 * @param string $sDir
	 * @param int $iPermissions
	 * @return bool
	 */
	public function md($sDir, $iPermissions = 0777) {
		$sId = self::_parse ( $sDir );
		if ($this->_aInfo [$sId] ['scheme'] == 'http') {
			return false;
		} else if ($this->_aInfo [$sId] ['scheme'] == 'file') {
			if (is_dir ( $sDir )) {
				return true;
			} else {
				return self::_md ( $this->_aInfo [$sId] ['path'], $iPermissions );
			}
		} else {
			$oObject = self::_getObject ( $sId );
			return $oObject->md ( $this->_aInfo [$sId] ['path'], $iPermissions );
		}
	}
	
	private function _getObject($sId) {
		$sClassName = ucfirst ( $this->_aInfo [$sId] ['scheme'] );
		$oObject = Base::loadClass ( $sClassName );
		return $oObject;
	}
	
	private function _md($sDir, $iPermissions) {
		if (! is_dir ( dirname ( $sDir ) )) {
			self::_md ( dirname ( $sDir ), $iPermissions );
		}
		return @mkdir ( $sDir, $iPermissions );
	}
	
	public function cp($sSrcFile, $sDestFile) {
		if (! is_file ( $sSrcFile )) {
			return false;
		} else {
			$sDir = dirname ( $sDestFile );
			if (! is_dir ( $sDir )) {
				self::md ( $sDir );
				return @copy ( $sSrcFile, $sDestFile );
			}
		}
		return true;
	}
	
	/**
	 * 删除目录或文件
	 *
	 * @param string $sFile
	 * @return bool
	 */
	public function rm($sFile) {
		if (is_dir ( $sFile )) {
			$aFile = scandir ( $sFile );
			$iCount = count ( $aFile );
			for($i = 2; $i < $iCount; $i ++) {
				self::rm ( $sFile . '/' . $aFile [$i] );
			}
			return @rmdir ( $sFile );
		} else {
			return @unlink ( $sFile );
		}
	}
	
	public function getMime($sFile, $sReturn = 'mime') {
		if ($this->_oFileInfo === null) {
			self::_fileInfo ();
		}
		if (is_file ( $sFile )) {
			$sMime = $this->_oFileInfo->file ( $sFile );
			$aMime = preg_split ( '/;\s+charset=/', $sMime );
			switch (strtolower ( $sReturn )) {
				case 'all' :
					return array ($aMime [0], $aMime [1], 'mime' => $aMime [0], 'charset' => $aMime [1] );
				case 'charset' :
					return $aMime [1];
				default :
					return $aMime [0];
			}
		} else {
			return false;
		}
	}
	
	private function _fileInfo() {
		try {
			if (! extension_loaded ( 'fileinfo' )) {
				new ExceptionExt ( '模块fileinfo没有安装' );
			}
		} catch ( ExceptionExt $e ) {
			$e->showError ();
		}
		
		$sPath = LIB . '/magic.mime';
		if (! is_file ( $sPath )) {
			$sPath = Base::getConf ( 'file.magic' );
			$sPath = $sPath ? $sPath : '/usr/share/misc/magic.mime';
		}
		$this->_oFileInfo = new finfo ( FILEINFO_MIME, $sPath );
		return true;
	}
}
?>